package com.sun.config;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * 分布式锁redission的配置
 */
@Slf4j
@Configuration
public class RedissonConfig {

    private ConfigService configService;  //nacos服务
    @Autowired
    private NacosClientConfig nacosClientConfig;

    private static final String DATA_ID = "redission-config.yml";

    private static final String GROUP = "DEFAULT_GROUP";


    /**
     * 可以尝试在nacos配置信息
     *
     * @return
     * @throws IOException
     */
    @Bean
    public RedissonClient redisson() {
        // 初始化 Nacos 配置客户端
        Config config = null;
        try {
            configService = initConfigService();
            if (null == configService) {
                log.error("init config service fail");
                return Redisson.create();
            }
            // 通过 Nacos Config 获取配置信息
            String configInfo = configService.getConfig(
                    DATA_ID,
                    GROUP,
                    nacosClientConfig.DEFAULT_TIMEOUT
            );
            config = Config.fromYAML(configInfo);
            //设置监听器
            dynamicLoadConfigByNacosListener(DATA_ID, GROUP);
        } catch (NacosException | IOException e) {
            e.printStackTrace();
        }
        return Redisson.create(config);
    }


    /**
     * <h2>监听 Nacos 下发的动态配置</h2>
     */
    private void dynamicLoadConfigByNacosListener(String dataId, String group) {
        try {
            // 给 Nacos Config 客户端增加一个监听器
            configService.addListener(dataId, group, new Listener() {

                /**
                 * 自己提供线程池执行操作
                 * */
                @Override
                public Executor getExecutor() {
                    return null;
                }

                /**
                 * 监听器收到配置更新
                 * @param configInfo Nacos 中最新的配置定义
                 * */
                @SneakyThrows
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("start to update config: [{}]", configInfo);
                    Config config = Config.fromYAML(configInfo);
                    log.info("update route: [{}]", configInfo);
                    Redisson.create(config);
                }
            });
        } catch (NacosException ex) {
            log.error("dynamic update gateway config error: [{}]", ex.getMessage(), ex);
        }
    }


    /**
     * 初始化 Nacos Config
     */
    private ConfigService initConfigService() {
        try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr", nacosClientConfig.NACOS_SERVER_ADDR);
            properties.setProperty("namespace", nacosClientConfig.NACOS_NAMESPACE);
            return configService = NacosFactory.createConfigService(properties);
        } catch (Exception ex) {
            log.error("init redisson nacos config error: [{}]", ex.getMessage(), ex);
            return null;
        }
    }


    /**
     * ***********************************************************
     * 或者，在 application.yml 中配置如下:
     * spring:
     * redis:
     * redisson:
     * config: classpath:redisson-config.yaml
     * ***********************************************************
     *
     * @return
     * @throws IOException
     */
//    @Bean
//    public RedissonClient redisson() throws IOException {
//        // 两种读取方式，Config.fromYAML 和 Config.fromJSON
//        // Config config = Config.fromJSON(RedissonConfiguration.class.getClassLoader().getResource("redisson-config.json"));
//        Config config = Config.fromYAML(RedissonConfiguration.class.getClassLoader().getResource("redisson-config.yml"));
//        return (Redisson) Redisson.create(config);
//
//        //或者这样写
////        RedissonClient redisson = Redisson.create(
////                Config.fromYAML(new ClassPathResource("redisson-config.yml").getInputStream()));
////        return  redisson;
//    }


}
